﻿#ifndef OBSERVER_IMPL_BASE_HPP
#define OBSERVER_IMPL_BASE_HPP

#include <map>

template <typename ReturnT, typename ParamT>
class ReceiverImplBase;

template <typename ReturnT, typename ParamT>
class ObserverImplBase
{
public:
    virtual void AddReceiver(ReceiverImplBase<ReturnT, ParamT>* receiver) = 0;
    virtual void RemoveReceiver(ReceiverImplBase<ReturnT, ParamT>* receiver) = 0;
    virtual void RemoveAll() = 0;
    virtual ReturnT Broadcast(ParamT param) = 0;
    virtual ReturnT RBroadcast(ParamT param) = 0;
    virtual ReturnT Notify(ParamT param) = 0;
};

template <typename ReturnT, typename ParamT>
class ReceiverImplBase
{
public:
    virtual void AddObserver(ObserverImplBase<ReturnT, ParamT>* observer) = 0;
    virtual void RemoveObserver() = 0;
    virtual ReturnT Receive(ParamT param) = 0;
    virtual ReturnT Respond(ParamT param, ObserverImplBase<ReturnT, ParamT>* observer) = 0;
};

template <typename ReturnT, typename ParamT>
class ReceiverImpl;

template <typename ReturnT, typename ParamT>
class ObserverImpl : public ObserverImplBase<ReturnT, ParamT>
{
    template <typename ReturnT, typename ParamT>
    friend class Iterator;
public:
    ObserverImpl()
    {}

    virtual ~ObserverImpl()    {}

    virtual void AddReceiver(ReceiverImplBase<ReturnT, ParamT>* receiver)
    {
        if (receiver == NULL)
            return;

        receivers_.push_back(receiver);
        receiver->AddObserver(this);
    }

    virtual void RemoveReceiver(ReceiverImplBase<ReturnT, ParamT>* receiver)
    {
        if (receiver == NULL)
            return;

        ReceiversVector::iterator it = receivers_.begin();
        for (; it != receivers_.end(); ++it)
        {
            if (*it == receiver)
            {
                receivers_.erase(it);
                break;
            }
        }
    }

    virtual void RemoveAll() 
    {
        ReceiversVector::iterator it = receivers_.begin();
        for (; it != receivers_.end(); )
        {
            it = receivers_.erase(it);
        }
    }

    virtual ReturnT Broadcast(ParamT param)
    {
        ReceiversVector::iterator it = receivers_.begin();
        for (; it != receivers_.end(); ++it)
        {
            (*it)->Receive(param);
        }

        return ReturnT();
    }

    virtual ReturnT RBroadcast(ParamT param)
    {
        ReceiversVector::reverse_iterator it = receivers_.rbegin();
        for (; it != receivers_.rend(); ++it)
        {
            (*it)->Receive(param);
        }

        return ReturnT();
    }

    virtual ReturnT Notify(ParamT param)
    {
        ReceiversVector::iterator it = receivers_.begin();
        for (; it != receivers_.end(); ++it)
        {
            (*it)->Respond(param, this);
        }

        return ReturnT();
    }

    template <typename ReturnT, typename ParamT>
    class Iterator
    {
        ObserverImpl<ReturnT, ParamT> & _tbl;
        DWORD index;
        ReceiverImplBase<ReturnT, ParamT>* ptr;
    public:
        Iterator( ObserverImpl & table )
            : _tbl( table ), index(0), ptr(NULL)
        {}

        Iterator( const Iterator & v )
            : _tbl( v._tbl ), index(v.index), ptr(v.ptr)
        {}

        ReceiverImplBase<ReturnT, ParamT>* next()
        {
            if ( index >= _tbl.receivers_.size() )
                return NULL;

            for ( ; index < _tbl.receivers_.size(); )
            {
                ptr = _tbl.receivers_[ index++ ];
                if ( ptr )
                    return ptr;
            }
            return NULL;
        }
    };

protected:
    typedef std::vector<ReceiverImplBase<ReturnT, ParamT>*> ReceiversVector;
    ReceiversVector receivers_;
};


template <typename ReturnT, typename ParamT>
class ReceiverImpl : public ReceiverImplBase<ReturnT, ParamT>
{
public:
    ReceiverImpl()
    {}

    virtual ~ReceiverImpl()    {}

    virtual void AddObserver(ObserverImplBase<ReturnT, ParamT>* observer)
    {
        observers_.push_back(observer);
    }

    virtual void RemoveObserver()
    {
        ObserversVector::iterator it = observers_.begin();
        for (; it != observers_.end(); ++it)
        {
            (*it)->RemoveReceiver(this);
        }
    }

    virtual ReturnT Receive(ParamT param)
    {
        return ReturnT();
    }

    virtual ReturnT Respond(ParamT param, ObserverImplBase<ReturnT, ParamT>* observer)
    {
        return ReturnT();
    }

protected:
    typedef std::vector<ObserverImplBase<ReturnT, ParamT>*> ObserversVector;
    ObserversVector observers_;
};

#endif // OBSERVER_IMPL_BASE_HPP